#include "../include/tlv.h"
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>

int tlv_send(int sockfd,uint32_t type,uint32_t length,const uint8_t *value){
    if(length>TLV_VALUE_MAX_SIZE){return -1;}

    uint8_t buffer[TLV_BUFFER_MAX_SIZE];
    uint32_t type_net_byte=htonl(type);
    uint32_t length_net_byte=htonl(length);
    memcpy(buffer,&type_net_byte,sizeof(type));
    memcpy(buffer+sizeof(type),&length_net_byte,sizeof(length));
    memcpy(buffer+sizeof(type)+sizeof(length),value,length);

    if(send(sockfd,buffer,sizeof(type)+sizeof(length)+length,MSG_NOSIGNAL)==-1){return -1;}

    return 0;
}

int tlv_recv(int sockfd,uint32_t *type,uint32_t *length,uint8_t *value){
    if(recv(sockfd,type,sizeof(uint32_t),MSG_WAITALL)!=sizeof(uint32_t)){return -1;}
    *type=ntohl(*type);

    if(recv(sockfd,length,sizeof(uint32_t),MSG_WAITALL)!=sizeof(uint32_t)){return -1;}
    *length=ntohl(*length);
    
    if(recv(sockfd,value,*length,MSG_WAITALL)!=*length){return -1;}

    return 0;
}

int tlv_listen(int sockfd,uint32_t *type,uint32_t *length,uint8_t *value){
    if(tlv_recv(sockfd,type,length,value)==-1){return -1;}
    return 0;
}

int tlv_response(int sockfd,uint32_t response_code,uint32_t length,const uint8_t *value){
    if(length+sizeof(response_code)>TLV_VALUE_MAX_SIZE){return -1;}

    uint32_t type_net_byte=htonl(RESPONSE);
    uint32_t length_net_byte=htonl(length+sizeof(response_code));
    uint32_t response_code_net_byte=htonl(response_code);

    uint8_t buffer[TLV_BUFFER_MAX_SIZE];

    size_t offset=0;

    size_t size=sizeof(type_net_byte);
    memcpy(buffer+offset,&type_net_byte,size);
    offset+=size;

    size=sizeof(length_net_byte);
    memcpy(buffer+offset,&length_net_byte,size);
    offset+=size;
    
    size=sizeof(response_code_net_byte);
    memcpy(buffer+offset,&response_code_net_byte,size);
    offset+=size;
    
    size=length;
    memcpy(buffer+offset,value,size);
    offset+=size;

    if(send(sockfd,buffer,offset,MSG_NOSIGNAL)==-1){return -1;}

    return 0;
}
